/***************************************************************************
 *   Copyright (C) 2009 by Bernhard Neuhofer   *
 *   mail@bneu.at   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

using namespace std;

#include <iostream>
#include <cstdlib>
#include <assert.h>
#include "corbaAddressServer.h"
#include <string>
#include "CServiceSM.h"
#include "CServiceMCP.h"
#include "../tools/log.h"
#include <boost/program_options.hpp>

namespace po = boost::program_options;

unsigned int debuglevel=0;

int main(int argc,char** args)

{
    po::options_description desc ( "Allowed options" );
    desc.add_options()
    ( "help,h", "produce help message" )
    ( "debug,d", po::value< unsigned int >(), "set the debug level [0-3]. Default 0" )
    ;
    po::variables_map vm;
    po::store ( po::parse_command_line ( argc, args, desc ), vm );
    po::notify ( vm );
    if ( vm.count ( "help" ) )
    {
        cout << desc << "\n";
        exit ( 0 );
    }
    if ( vm.count ( "debug" ) )
    {
        debuglevel=vm["debug"].as<unsigned int>();
        if ( debuglevel>3 ) debuglevel=3;
        cout <<"Setting DebugLevel to: "<<debuglevel<<endl;
        switch ( debuglevel )
        {
        case 0:
            FILELog::ReportingLevel() = FILELog::FromString ( "ERROR" );
            break;
        case 1:
            FILELog::ReportingLevel() = FILELog::FromString ( "WARNING" );
            break;
        case 2:
            FILELog::ReportingLevel() = FILELog::FromString ( "INFO" );
            break;
        case 3:
            FILELog::ReportingLevel() = FILELog::FromString ( "DEBUG" );
            break;
        default:
            FILELog::ReportingLevel() = FILELog::FromString ( "ERROR" );
            break;
        }
    }
    else
    {
        cout <<"Using default DebugLevel: 0 "<<endl;
        FILELog::ReportingLevel() = FILELog::FromString ( "ERROR" );
    }

    cout <<"Starting AddressServer"<<endl;

    try {
        //Initialize CORBA ORB - "orb"
        CORBA::ORB_var orb=CORBA::ORB_init(argc,args);

        //Servant must register with POA in order to be made available for client
        // Get reference to the RootPOA
        CORBA::Object_var obj=orb->resolve_initial_references("RootPOA");
        PortableServer::POA_var _poa=PortableServer::POA::_narrow(obj.in());


        //Resolve CORBA NameService
        CORBA::Object_var NameServiceObj=orb->resolve_initial_references("NameService");
        assert(!CORBA::is_nil(NameServiceObj.in()));


        CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(NameServiceObj.in());
        assert(!CORBA::is_nil(nc.in()));
        CosNaming::Name nameContext;
        CosNaming::Name SMname;
        CosNaming::Name MCPname;



        CServiceSM_i* SMService= new CServiceSM_i();
        CServiceMCP_i* MCPService= new CServiceMCP_i();

        PortableServer::ObjectId_var mySMService_oid =_poa->activate_object(SMService);
        PortableServer::ObjectId_var myMCPService_oid =_poa->activate_object(MCPService);

        CORBA::Object_var SM_obj =SMService->_this();
        CORBA::String_var SM_sior(orb->object_to_string(SM_obj.in()));
        cerr<<"SMService:'"<<(char*)SM_sior<<"'"<<endl;

        CORBA::Object_var MCP_obj =MCPService->_this();
        CORBA::String_var MCP_sior(orb->object_to_string(MCP_obj.in()));
        cerr<<"MCPService:'"<<(char*)MCP_sior<<"'"<<endl;


        //Register AddressServer at the CORBA NameService
        try {
            CosNaming::NamingContext_var nc1 = nc->new_context();
            nameContext.length(1);
            nameContext[0].id=CORBA::string_dup("AddressServer");
            nameContext[0].kind=CORBA::string_dup("");
            nc->rebind_context(nameContext,nc1);


            SMname.length(2);
            SMname[0].id=CORBA::string_dup("AddressServer");
            SMname[0].kind=CORBA::string_dup("");
            SMname[1].id=CORBA::string_dup("SM");
            SMname[1].kind=CORBA::string_dup("");
            nc->rebind(SMname,SM_obj.in());



            MCPname.length(2);
            MCPname[0].id=CORBA::string_dup("AddressServer");
            MCPname[0].kind=CORBA::string_dup("");
            MCPname[1].id=CORBA::string_dup("MCP");
            MCPname[1].kind=CORBA::string_dup("");
            nc->rebind(MCPname,MCP_obj.in());
        }
        catch (CosNaming::NamingContext::NotFound & nf)
        {
            FILE_LOG(logERROR)<<"Caught CosNaming::notFoundException."<<endl;
        }
        catch (CosNaming::NamingContext::CannotProceed & nf)
        {
            FILE_LOG(logERROR)<<"Caught CosNaming::CannotProceed."<<endl;
        }
        catch (CosNaming::NamingContext::InvalidName & nf)
        {
            FILE_LOG(logERROR)<<"Caught CosNaming::InvalidName."<<endl;
        }
        catch (CosNaming::NamingContext::AlreadyBound & nf)
        {
            FILE_LOG(logERROR)<<"Caught CosNaming::AlreadyBound."<<endl;
        }
        catch (CosNaming::NamingContext::NotEmpty & nf)
        {
            FILE_LOG(logERROR)<<"Caught CosNaming::NotEmpty."<<endl;
        }

        SMService->_remove_ref();
        MCPService->_remove_ref();

        PortableServer::POAManager_var pmgr =_poa->the_POAManager();
        pmgr->activate();

        orb->run();

        orb->destroy();
        free(nameContext[0].id);
        free(nameContext[0].kind);

        free(SMname[1].id);
        free(SMname[1].kind);
        free(SMname[0].id);
        free(SMname[0].kind);

        free(MCPname[1].id);
        free(MCPname[1].kind);
        free(MCPname[0].id);
        free(MCPname[0].kind);


    }
    catch (CORBA::SystemException&)
    {
        FILE_LOG(logERROR)<<"Caught CORBA::SystemException."<<endl;
    }
    catch (CORBA::Exception&)
    {
        FILE_LOG(logERROR)<<"Caught CORBA::Exception."<<endl;
    }
    catch (omniORB::fatalException& fe)
    {
        FILE_LOG(logERROR)<<"Caught omniORB::fatalException:"<<endl;
        FILE_LOG(logERROR)<<" file: "<<fe.file()<<endl;
        FILE_LOG(logERROR)<<" line: "<<fe.line()<<endl;
        FILE_LOG(logERROR)<<" mesg: "<<fe.errmsg()<<endl;
    }
    catch (...)
    {
        FILE_LOG(logERROR)<<"Caught unknown exception."<<endl;
    }
    return 0;
}
